--- see 'https://github.com/Frege/frege/issues/270 Issue #270'
{-- 
    ## Problem 1

    When the names of type variables of let bound functions is the same
    as in the enclosing function, errors may occur. Specifically, *whiteSpace* references
    *languageDef* and while the frege compiler can sort out its type variables quite fine
    in type checking, it ruins it in code generation by doing something like:

        final<st> ... whiteSpace() { .... languageDef.<st>commentStart ... }

    and the Java compiler complains that the both *st* types are actually different.

    This can only happen in the rare cases where type annotated let bindings cannot be 
    lifted to the top level.

    Solution: alpha conversion of annotations for let bound functions. (This should also
    better the error message problem "type is st, expected st") 

    ## Problem 2

    For some reason the "lexeme" function, when written without the superfluous () argument
    is generated as a function, but the code generator thinks it is  lambda. This must be
    a (hopefully minor) glitch in the let-code generator.

-}
module tests.comp.Issue270 where


makeTokenParser :: LanguageDef st -> TokenParser st
makeTokenParser languageDef
    = TokenParser{ lexeme = lexeme, 
                   whiteSpace = whiteSpace, 
                   natural = natural,
                   integer = integer, }
    where
    whiteSpace :: forall st. CharParser st ()
    whiteSpace
        | noLine && noMulti = undefined
        | noLine            = undefined
        where
          noLine   = null []
          noMulti  = null (languageDef.commentStart)
    
    integer = lexeme  int
    natural = lexeme  nat
    int = undefined
    nat = undefined
    
    lexeme :: forall a st. CharParser st a -> CharParser st a
    lexeme  p = do { x <- p; whiteSpace; return x }




-- Necessary Definitions
data LanguageDef st = LanguageDef { commentStart :: String }                           

data TokenParser st = TokenParser { whiteSpace :: CharParser st ()
                                  , lexeme     :: forall a. CharParser st a -> CharParser st a
                                  , integer    :: CharParser st Integer
                                  , natural    :: CharParser st Integer }

type CharParser st a    = GenParser Char st a
type Parser a           = GenParser Char () a
data GenParser tok st a = Parser (State tok st -> Consumed (Reply tok st a))
data Consumed a     = Consumed a
data State tok st   = State
data Reply tok st a = Ok a (State tok st) String

instance Monad (GenParser tok st) where
  pure x     = undefined
  p >>= f    = undefined

main = println "compiled, so okay"